import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';

class LinePainter extends CustomPainter {
  Paint bgPaint =
      Paint()
        ..color = Colors.white
        ..isAntiAlias = true
        ..style = PaintingStyle.fill;

  Paint linePaint =
      Paint()
        ..color = Colors.red
        ..isAntiAlias = true
        ..strokeWidth = 4
        ..style = PaintingStyle.stroke;

  Paint pointPaint =
      Paint()
        ..color = Colors.green
        ..isAntiAlias = true
        ..strokeWidth = 4
        ..strokeCap = StrokeCap.round
        ..style = PaintingStyle.fill;

  Paint areaPaint =
  Paint()
    ..color = Colors.green
    ..isAntiAlias = true
    ..style = PaintingStyle.fill;

  Paint clearPaint =
  Paint()
    ..isAntiAlias = true
    ..color = const Color(0x00000000)
    ..style = PaintingStyle.fill
    ..blendMode = BlendMode.dstIn;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(Rect.fromLTRB(0, 0, size.width, 180), bgPaint);
    //canvas.drawLine(Offset(0, 0), Offset(100, 100), linePaint);

    Path path = Path();

    var temp = Offset.zero;
    var points = getPoints(size);
    int len = points.length;
    path.moveTo(points.first.dx, points.first.dy);
    for (int i = 1; i < points.length; i++) {
      final current = points[i];

      final previous = Offset(points[i - 1].dx, points[i - 1].dy);

      /// next point
      final next = Offset(
        points[i + 1 < len ? i + 1 : i].dx,
        points[i + 1 < len ? i + 1 : i].dy,
      );

      final controlPoint1 = previous + temp;

      temp = ((next - previous) / 2) * 0.35;

      final controlPoint2 = current - temp;

      path.cubicTo(
        controlPoint1.dx,
        controlPoint1.dy,
        controlPoint2.dx,
        controlPoint2.dy,
        current.dx,
        current.dy,
      );
    }
    canvas.drawPath(path, linePaint);

    var belowBarPath1 = Path.from(path);

    var x = points[len - 1].dx;
    //bottom right
    belowBarPath1.lineTo(x, 90);
    //bottom left
    belowBarPath1.lineTo(points[0].dx, 90);
    //top left
    belowBarPath1.lineTo(points[0].dx,points[0].dy);
    belowBarPath1.close();

    var belowFullBarPath1 = Path.from(path);
    belowFullBarPath1.lineTo(x, 0);
    //bottom left
    belowFullBarPath1.lineTo(points[0].dx, 0);
    //top left
    belowFullBarPath1.lineTo(points[0].dx,points[0].dy);
    belowFullBarPath1.close();

    // canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
    //
    // canvas.restore();


    var belowBarPath2 = Path.from(path);

    //bottom right
    belowBarPath2.lineTo(x, 110);
    //bottom left
    belowBarPath2.lineTo(points[0].dx, 110);
    //top left
    belowBarPath2.lineTo(points[0].dx,points[0].dy);
    belowBarPath2.close();


    var belowFullBarPath2 = Path.from(path);
    belowFullBarPath2.lineTo(x, 0);
    //bottom left
    belowFullBarPath2.lineTo(points[0].dx, 0);
    //top left
    belowFullBarPath2.lineTo(points[0].dx,points[0].dy);
    belowFullBarPath2.close();


    var belowBarPath3 = Path.from(path);

    //bottom right
    belowBarPath3.lineTo(x, 120);
    //bottom left
    belowBarPath3.lineTo(points[0].dx, 120);
    //top left
    belowBarPath3.lineTo(points[0].dx,points[0].dy);
    belowBarPath3.close();

    var belowBarPath4 = Path.from(path);

    //bottom right
    belowBarPath4.lineTo(x, 160);
    //bottom left
    belowBarPath4.lineTo(points[0].dx, 160);
    //top left
    belowBarPath4.lineTo(points[0].dx,points[0].dy);
    belowBarPath4.close();

    Paint paint = Paint();
    paint.isAntiAlias = true;
    paint.color = Colors.greenAccent;
    paint.blendMode = BlendMode.dstOver;

    canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
    canvas.drawPath(belowBarPath1, areaPaint);
    //canvas.drawPath(belowFullBarPath1, clearPaint);
    canvas.drawPath(belowBarPath2, paint);
    paint.color = Colors.blue;
    canvas.drawPath(belowBarPath3, paint);
    paint.color = Colors.yellow;
    canvas.drawPath(belowBarPath4, paint);
    canvas.drawPath(belowFullBarPath2, clearPaint);
    canvas.restore();
  }

  final int height = 180;

  List<Offset> getPoints(Size size) {
    List<Offset> points = [];
    points.add(Offset(0, height - 0 ));
    points.add(Offset(20, height - 20));
    points.add(Offset(40, height - 40));
    points.add(Offset(60, height - 60));
    points.add(Offset(80, height - 80));
    points.add(Offset(100, height - 100));
    points.add(Offset(120, height - 120));
    points.add(Offset(160, height - 90));
    points.add(Offset(180, height - 130));
    points.add(Offset(220, height - 150));
    points.add(Offset(280, height - 60));
    points.add(Offset(size.width, height - 80));
    return points;
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
